Skip to content

Show DR for verified partner websites - #4024

Merged
steven-tey merged 3 commits into
mainfrom
domain-rating
Jun 11, 2026
Merged

Show DR for verified partner websites#4024
steven-tey merged 3 commits into
mainfrom
domain-rating

Conversation

@steven-tey

@steven-tey steven-tey commented Jun 10, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Fetch and display Website domain rating (DR) for verified website partners.
    • Cron endpoints process partner-platform stats in paginated daily batches and schedule subsequent batches.
  • Improvements

    • Smarter change-detection to skip unnecessary platform updates (includes avatar/identifier checks).
    • Consolidated platform stat display into a single stat string for clearer summaries.
  • UI

    • Redesigned partner card layout, sorted verified platforms first, updated invite controls and star button styling.
  • Other

    • Website DR shown in partner forms.

@vercel

vercel Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dub Ready Ready Preview Jun 10, 2026 11:57pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Ahrefs domain-rating collection and website cron batch processing with Qstash continuation; refactors YouTube cron for cursor-based pagination and richer change detection; surfaces domain rating as "N DR" in partner platform UI and forms; refactors partner card UI and tweaks button styling.

Changes

Partner Platforms Metrics Collection

Layer / File(s) Summary
Ahrefs domain rating helper
apps/web/app/(ee)/api/cron/partner-platforms/website/get-domain-rating.ts
New exported getDomainRating(target: string) fetches Ahrefs free endpoint, validates JSON with Zod, throws on non-OK responses, and returns rounded numeric domain rating.
Website platform cron batch processor
apps/web/app/(ee)/api/cron/partner-platforms/website/route.ts
Dynamic POST cron route processes verified website partner records in batches, calls getDomainRating, updates subscribers and lastCheckedAt when changed, logs per-record failures, and publishes Qstash continuation when batch is full.
YouTube cron pagination & change detection
apps/web/app/(ee)/api/cron/partner-platforms/youtube/route.ts
POST handler now parses startingAfter from request body, queries Prisma with cursor-based take/cursor/skip ordering, computes avatarUrl and conditional identifier, detects changes across subscribers/posts/views/avatar/identifier, skips no-op updates, and schedules next batch via Qstash when full.
Platform stat fields and form display
apps/web/lib/partners/partner-platforms.ts, apps/web/ui/partners/partner-platforms-form.tsx, apps/web/ui/partners/partner-star-button.tsx
Adds verifiedAt and optional stat to platform field generator return shape. Website exposes "{subscribers} DR" and sets stat when verified; other platforms set stat from subscribers. FormRow adds website-specific "N DR" verified info; star button base styling adjusted.
Network partner card refactor & actions
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx
Refactors partner card UI: route-aware invite visibility, changed joinedAt display, verified-first sorting, platforms grid layout, extracted NetworkPartnerCardActions for invite/star flows and invite-limit/trial handling, updated tooltip/PlatformStatCard rendering, switched ListRow overflow to ResizeObserver, and styling tweaks.
Maintenance comment
apps/web/app/(ee)/api/cron/partner-platforms/route.ts
Minor comment wording adjustment in Prisma eligibility filter describing partner verification/trust state.

Sequence Diagram

sequenceDiagram
  participant Cron as Cron/Qstash
  participant Route as Website Cron Route
  participant Prisma as Prisma DB
  participant Ahrefs as Ahrefs API
  participant Qstash as Qstash

  Cron->>Route: POST /api/cron/partner-platforms/website (startingAfter)
  Route->>Prisma: Query verified website platforms (batch, cursor-paginated)
  Prisma-->>Route: Website partner records

  loop For each website record
    Route->>Ahrefs: GET domain-rating-free (normalized domain)
    Ahrefs-->>Route: JSON with domain_rating
    Route->>Prisma: Update subscribers & lastCheckedAt (if changed)
  end

  alt Batch full (size === BATCH_SIZE)
    Route->>Qstash: publishJSON next batch (startingAfter = last id)
    Qstash-->>Route: scheduled
  else Final partial batch
    Route-->>Route: log completion
  end

  Route-->>Cron: 200 OK
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • dubinc/dub#3988: Related UI change adjusting TrustedPartnerBadge sizing that aligns with partner card badge updates.

Suggested reviewers

  • pepeladeira

Poem

🐰 I hop through domains and code so spry,
Fetching ratings from Ahrefs from the sky,
Batches march on, cursors glide,
Qstash nudges the next batch ride,
Partner stats now whisper "N DR" with pride.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature being added—displaying Domain Rating (DR) for verified partner websites. It directly aligns with the primary changes across multiple files that enable DR display functionality.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch domain-rating

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/app/(ee)/api/cron/partner-platforms/youtube/route.ts (1)

91-98: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

find() only refreshes the first row for a shared channel ID.

Line 92 uses find(), so one YouTube payload only updates the first PartnerPlatform whose platformId matches channel.id. The Prisma schema shown for PartnerPlatform does not make platformId unique, so any additional verified rows pointing at the same channel will stay stale. Pre-group by platformId or use filter() here and apply the same update to every match.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(ee)/api/cron/partner-platforms/youtube/route.ts around lines
91 - 98, The current updateChunk.map callback uses channelChunk.find(...) which
only returns the first PartnerPlatform with a matching platformId, so duplicate
PartnerPlatform rows with the same platformId remain stale; change the logic
inside the updateChunk.map callback to collect all matches (e.g., use
channelChunk.filter(p => p.platformId === channel.id) or pre-group channelChunk
by platformId) and then apply the same update to every matched PartnerPlatform
instead of a single partnerPlatform — update any code paths referencing
partnerPlatform (the variable from the find call) to iterate over the matches
and run the existing update logic per item.
🧹 Nitpick comments (1)
apps/web/lib/partners/partner-platforms.ts (1)

35-40: ⚡ Quick win

Consider extracting domain rating formatting into a shared helper.

The domain rating formatting logic ${Number(website.subscribers)} DR is duplicated in apps/web/ui/partners/partner-platforms-form.tsx (lines 688-698). To maintain consistency and reduce the risk of divergence, consider extracting this into a shared helper function.

♻️ Suggested refactor

Create a helper function in this file:

function formatDomainRating(subscribers: bigint | null): string | null {
  const domainRating = subscribers ?? 0n;
  return domainRating > 0n ? `${Number(domainRating)} DR` : null;
}

Then use it in both locations:

  info: [
-   website?.subscribers && website?.verifiedAt
-     ? `${Number(website.subscribers)} DR`
-     : null,
+   website?.verifiedAt ? formatDomainRating(website.subscribers) : null,
  ].filter(Boolean),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/partners/partner-platforms.ts` around lines 35 - 40, Extract the
duplicated domain rating formatting into a shared helper named
formatDomainRating(subscribers) that returns a string like "N DR" or null;
replace the inline expression in partner-platforms.ts (the info array entry that
uses website?.subscribers) with a call to
formatDomainRating(website?.subscribers) and update partner-platforms-form.tsx
to call the same helper instead of repeating `${Number(...)} DR`; ensure the
helper treats bigint|null safely (defaults to 0n) and returns null for zero or
missing values so both components keep identical behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@apps/web/app/`(ee)/api/cron/partner-platforms/youtube/route.ts:
- Around line 91-98: The current updateChunk.map callback uses
channelChunk.find(...) which only returns the first PartnerPlatform with a
matching platformId, so duplicate PartnerPlatform rows with the same platformId
remain stale; change the logic inside the updateChunk.map callback to collect
all matches (e.g., use channelChunk.filter(p => p.platformId === channel.id) or
pre-group channelChunk by platformId) and then apply the same update to every
matched PartnerPlatform instead of a single partnerPlatform — update any code
paths referencing partnerPlatform (the variable from the find call) to iterate
over the matches and run the existing update logic per item.

---

Nitpick comments:
In `@apps/web/lib/partners/partner-platforms.ts`:
- Around line 35-40: Extract the duplicated domain rating formatting into a
shared helper named formatDomainRating(subscribers) that returns a string like
"N DR" or null; replace the inline expression in partner-platforms.ts (the info
array entry that uses website?.subscribers) with a call to
formatDomainRating(website?.subscribers) and update partner-platforms-form.tsx
to call the same helper instead of repeating `${Number(...)} DR`; ensure the
helper treats bigint|null safely (defaults to 0n) and returns null for zero or
missing values so both components keep identical behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 960416a3-e8f9-4fd4-a5de-f2e14053bf14

📥 Commits

Reviewing files that changed from the base of the PR and between 6f902f4 and 853172d.

📒 Files selected for processing (6)
  • apps/web/app/(ee)/api/cron/partner-platforms/route.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/website/get-domain-rating.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/website/route.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/youtube/route.ts
  • apps/web/lib/partners/partner-platforms.ts
  • apps/web/ui/partners/partner-platforms-form.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@apps/web/app/app.dub.co/`(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx:
- Around line 257-259: The current logic uses remainingInvites === 0 but
remainingInvites can be undefined while loading; change the logic in the
component that calls usePartnerNetworkInvitesUsage so that undefined is treated
as "loading" and prevents invites: compute an isLoading flag (e.g.,
remainingInvites === undefined), set atNetworkInviteLimit only when
remainingInvites !== undefined && remainingInvites === 0, and derive disabled as
isLoading || (atNetworkInviteLimit && !trialActive) so invites are blocked until
remainingInvites is known.
- Around line 355-368: As currently written As is set to "a" or "div" but the
element always receives anchor-only attributes (href, target, rel), which causes
invalid attributes on a div; update the render so that href/target/rel are only
applied when href is truthy (e.g., compute anchorProps when href exists and
spread them into the element) while still rendering As (the variable) and
keeping onClick={(e) => e.stopPropagation()} and content; reference the As
variable and the surrounding JSX (DynamicTooltipWrapper and the element that
receives href/target/rel) to locate where to conditionally apply those props.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f736e2b9-7c20-48fb-a7b9-b610dd2b4e7a

📥 Commits

Reviewing files that changed from the base of the PR and between 853172d and de3d607.

📒 Files selected for processing (3)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx
  • apps/web/lib/partners/partner-platforms.ts
  • apps/web/ui/partners/partner-star-button.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/web/ui/partners/partner-star-button.tsx

@steven-tey

Copy link
Copy Markdown
Collaborator Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx (1)

261-263: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

remainingInvites may be undefined during initial load.

Per context snippet 1, usePartnerNetworkInvitesUsage returns remaining as number but it can be undefined while loading. The comparison remainingInvites === 0 evaluates to false when undefined, allowing invites before the limit is known.

🛡️ Proposed fix to handle undefined state
  const { remaining: remainingInvites } = usePartnerNetworkInvitesUsage();
- const atNetworkInviteLimit = remainingInvites === 0;
- const disabled = atNetworkInviteLimit && !trialActive;
+ const isLoadingInvites = remainingInvites === undefined;
+ const atNetworkInviteLimit = remainingInvites !== undefined && remainingInvites === 0;
+ const disabled = isLoadingInvites || (atNetworkInviteLimit && !trialActive);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/web/app/app.dub.co/`(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx
around lines 261 - 263, remainingInvites can be undefined during load so change
the boolean logic to explicitly check for undefined: compute
atNetworkInviteLimit as remainingInvites !== undefined && remainingInvites === 0
(using the value from usePartnerNetworkInvitesUsage), and ensure disabled uses
that guarded atNetworkInviteLimit together with trialActive so we don't
erroneously allow invites while remainingInvites is still loading.
🧹 Nitpick comments (3)
apps/web/app/(ee)/api/cron/partner-platforms/youtube/route.ts (1)

89-141: ⚡ Quick win

Individual update failures will abort the entire batch.

If any prisma.partnerPlatform.update throws (e.g., network error, constraint violation), Promise.all rejects immediately, causing the remaining channels in subsequent chunks to be skipped. Since this is a daily cron with potentially thousands of records, consider wrapping individual updates in try-catch to isolate failures and continue processing.

♻️ Suggested per-record error isolation
       await Promise.all(
         updateChunk.map(async (channel) => {
+          try {
           const partnerPlatform = channelChunk.find(
             (p) => p.platformId === channel.id,
           );
 
           if (!partnerPlatform) {
             return;
           }
 
           // ... existing logic ...
 
           console.log(
             `Updated YouTube stats for @${partnerPlatform.identifier}`,
             newStats,
           );
+          } catch (error) {
+            console.error(
+              `Failed to update YouTube stats for channel ${channel.id}:`,
+              error,
+            );
+          }
         }),
       );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(ee)/api/cron/partner-platforms/youtube/route.ts around lines
89 - 141, The batch uses Promise.all over updateChunk.map so a single failed
prisma.partnerPlatform.update will reject the whole chunk and abort remaining
work; modify the anonymous async map callback (the function iterating
updateChunks / processing channel and partnerPlatform) to catch errors
per-record—wrap the logic around the prisma.partnerPlatform.update (and any
awaiting work) in a try-catch (or switch to Promise.allSettled) and on error log
the channel/partnerPlatform id and continue so one failing update does not stop
other updates or subsequent chunks.
apps/web/app/(ee)/api/cron/partner-platforms/website/route.ts (1)

79-87: ⚡ Quick win

Use explicit BigInt conversion for consistency.

On line 72, the code explicitly converts domainRating to BigInt for comparison: BigInt(domainRating). For consistency and clarity, the Prisma update should also use explicit conversion rather than relying on Prisma's implicit number-to-BigInt conversion.

♻️ Proposed fix for explicit type conversion
 await prisma.partnerPlatform.update({
   where: {
     id: website.id,
   },
   data: {
-    subscribers: domainRating,
+    subscribers: BigInt(domainRating),
     lastCheckedAt: new Date(),
   },
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/app/`(ee)/api/cron/partner-platforms/website/route.ts around lines
79 - 87, The Prisma update call in prisma.partnerPlatform.update is assigning
subscribers: domainRating without explicit BigInt conversion; change that to use
BigInt(domainRating) so the update uses an explicit BigInt (e.g., set
subscribers to BigInt(domainRating)) when updating the record identified by
website.id and keep lastCheckedAt: new Date() unchanged.
apps/web/lib/partners/partner-platforms.ts (1)

38-46: ⚡ Quick win

Duplication: info and stat compute identical values for Website.

Both the info array entry and the stat field use the same logic and produce the same string value. Consider extracting this computation to reduce duplication:

♻️ Proposed refactor to eliminate duplication
+        const domainRatingStat =
+          website?.subscribers && website?.verifiedAt
+            ? `${Number(website.subscribers)} DR`
+            : null;
         info: [
-          website?.subscribers && website?.verifiedAt
-            ? `${Number(website.subscribers)} DR`
-            : null,
+          domainRatingStat,
         ].filter(Boolean),
-        stat:
-          website?.subscribers && website?.verifiedAt
-            ? `${Number(website.subscribers)} DR`
-            : null,
+        stat: domainRatingStat,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/lib/partners/partner-platforms.ts` around lines 38 - 46, The info
array entry and stat field duplicate the same conditional computation for
Website (using website?.subscribers and website?.verifiedAt); extract that logic
into a single const (e.g., computedSubscribersDR or getSubscribersDR) inside
partner-platforms.ts and use that variable in both places (assign info:
[computedSubscribersDR].filter(Boolean) and stat: computedSubscribersDR) so the
conditional string creation is centralized and duplication is removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/app/`(ee)/api/cron/partner-platforms/website/get-domain-rating.ts:
- Around line 10-17: The fetch to Ahrefs in get-domain-rating.ts has no timeout;
wrap the request with an AbortController and a timer: create an AbortController,
pass controller.signal into the fetch call (the one that assigns to response),
start a setTimeout that calls controller.abort() after a configurable timeout
(e.g., 5–10s), and clear the timeout once the fetch completes; also ensure any
fetch error due to abort (AbortError) is handled/translated into a proper
timeout error path in the same function so the cron job can proceed gracefully.
- Around line 10-17: The fetch call that assigns to response when calling Ahrefs
(`fetch(...domain-rating-free...)`) doesn't handle non-2xx or 429 responses;
update the logic in the get-domain-rating handler to detect HTTP 429 and other
non-2xx statuses, implement a bounded retry with exponential backoff (honoring
the Retry-After header when present), and limit concurrent calls (or use a
centralized rate-limiter/throttle) to keep total requests under Ahrefs' ~60/min
dynamic threshold; ensure retries are capped (max attempts) and failures
propagate a clear error after exhaustion.

---

Duplicate comments:
In
`@apps/web/app/app.dub.co/`(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx:
- Around line 261-263: remainingInvites can be undefined during load so change
the boolean logic to explicitly check for undefined: compute
atNetworkInviteLimit as remainingInvites !== undefined && remainingInvites === 0
(using the value from usePartnerNetworkInvitesUsage), and ensure disabled uses
that guarded atNetworkInviteLimit together with trialActive so we don't
erroneously allow invites while remainingInvites is still loading.

---

Nitpick comments:
In `@apps/web/app/`(ee)/api/cron/partner-platforms/website/route.ts:
- Around line 79-87: The Prisma update call in prisma.partnerPlatform.update is
assigning subscribers: domainRating without explicit BigInt conversion; change
that to use BigInt(domainRating) so the update uses an explicit BigInt (e.g.,
set subscribers to BigInt(domainRating)) when updating the record identified by
website.id and keep lastCheckedAt: new Date() unchanged.

In `@apps/web/app/`(ee)/api/cron/partner-platforms/youtube/route.ts:
- Around line 89-141: The batch uses Promise.all over updateChunk.map so a
single failed prisma.partnerPlatform.update will reject the whole chunk and
abort remaining work; modify the anonymous async map callback (the function
iterating updateChunks / processing channel and partnerPlatform) to catch errors
per-record—wrap the logic around the prisma.partnerPlatform.update (and any
awaiting work) in a try-catch (or switch to Promise.allSettled) and on error log
the channel/partnerPlatform id and continue so one failing update does not stop
other updates or subsequent chunks.

In `@apps/web/lib/partners/partner-platforms.ts`:
- Around line 38-46: The info array entry and stat field duplicate the same
conditional computation for Website (using website?.subscribers and
website?.verifiedAt); extract that logic into a single const (e.g.,
computedSubscribersDR or getSubscribersDR) inside partner-platforms.ts and use
that variable in both places (assign info:
[computedSubscribersDR].filter(Boolean) and stat: computedSubscribersDR) so the
conditional string creation is centralized and duplication is removed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7b40ec87-7983-4fca-801d-5104f8ead604

📥 Commits

Reviewing files that changed from the base of the PR and between 6f902f4 and 17a12a8.

📒 Files selected for processing (8)
  • apps/web/app/(ee)/api/cron/partner-platforms/route.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/website/get-domain-rating.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/website/route.ts
  • apps/web/app/(ee)/api/cron/partner-platforms/youtube/route.ts
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/network/network-partner-card.tsx
  • apps/web/lib/partners/partner-platforms.ts
  • apps/web/ui/partners/partner-platforms-form.tsx
  • apps/web/ui/partners/partner-star-button.tsx

@steven-tey
steven-tey merged commit 5479242 into main Jun 11, 2026
11 checks passed
@steven-tey
steven-tey deleted the domain-rating branch June 11, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant